package jmine.tec.web.wicket.resource;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import jmine.tec.utils.io.IOUtils;

import org.springframework.beans.factory.DisposableBean;

/**
 * {@link ResourceStore} que usa um arquivo temporario
 * 
 * @author takeshi
 */
public class DiskStoreResource implements ResourceStore, Serializable, DisposableBean {

    private final File temporaryFile;

    private final long length;

    private final boolean compress;

    /**
     * Equivalente a chamar {@link #DiskStoreResource(InputStream, boolean)} com true
     * 
     * @param input InputStream
     * @throws IOException e
     */
    public DiskStoreResource(InputStream input) throws IOException {
        this(input, true);
    }

    /**
     * C'tor
     * 
     * @param source InputStream
     * @param compress boolean
     * @throws IOException e
     */
    public DiskStoreResource(InputStream source, boolean compress) throws IOException {
        this.temporaryFile = createTemporaryFile();
        this.compress = compress;
        this.length = writeFile(source);
    }

    /**
     * Writes the data into the temporary file
     * 
     * @param source the data source
     * @return long
     * @throws IOException if an IOException is thrown either reading or writing
     */
    private long writeFile(InputStream source) throws IOException {
        OutputStream fout = this.compress ? new GZIPOutputStream(new FileOutputStream(temporaryFile)) : new FileOutputStream(temporaryFile);
        return IOUtils.copyFullyCloseGetTotal(source, fout);
    }

    /**
     * Creates and returns a temporary file reference. The file is deleted when this program ends.
     * 
     * @return {@link File}
     * @throws IOException e
     */
    private static File createTemporaryFile() throws IOException {
        File tmp = File.createTempFile("resource", ".bin");
        tmp.deleteOnExit();
        return tmp;
    }

    /**
     * {@inheritDoc}
     */
    public long length() {
        return this.length;
    }

    /**
     * {@inheritDoc}
     */
    public InputStream openNew() throws IOException {
        return compress ? new GZIPInputStream(new FileInputStream(temporaryFile)) : new FileInputStream(temporaryFile);
    }

    /**
     * {@inheritDoc}
     */
    public void destroy() throws Exception {
        if (this.temporaryFile != null) {
            if (!this.temporaryFile.delete()) {
                this.temporaryFile.deleteOnExit();
            }
        }
    }

}
